package qj.util;

import java.util.ArrayList;
import java.util.List;

public class CsvUtil {

    /**
     * Parse the csv string
     * @param csvString the the csv string
     * @return list of all csv tokens
     */
    public static List<String> tokenize(String csvString) {
        CsvReader csvReader = new CsvReader();
        for (char c : csvString.toCharArray()) {
            csvReader.onChar(c);
        }
        return csvReader.getResult();
    }

    /**
     * Read the csv content and return list of tokens
     */
    public static class CsvReader {
        public static final Character DOUBLE_QUOTE = '\"';
        public static final Character COMMA = ',';

        /**
         * Store the previous char
         */
        Character savedChar = null;

        ArrayList<String> result = new ArrayList<String>();

        /**
         * State of this reader is in string literal or not
         */
        boolean inStringLiteral = false;

        /**
         * Store the token being built
         */
        StringBuffer sb = new StringBuffer();

        /**
         * Called on each input character
         * @param c the input character
         */
        public void onChar(Character c) {
            if (!inStringLiteral && COMMA.equals(savedChar)) {
                finishToken();
            } else if (DOUBLE_QUOTE.equals( savedChar ) ) {
                if (DOUBLE_QUOTE.equals(c)) {
                    sb.append(DOUBLE_QUOTE);
                    c = null; // Processed
                } else {
                    inStringLiteral = !inStringLiteral;
                }
            } else if (savedChar != null) {
                sb.append(savedChar);
            }
            savedChar = c;
        }

        /**
         * Get the result list of tokens
         * @return The result list of tokens
         */
        public List<String> getResult() {
            onChar(null);
            finishToken();
            return result;
        }

        /**
         * Finish reading a token
         */
        private void finishToken() {
            if (sb.length() > 0) {
                result.add(sb.toString());
                sb.setLength(0);
            }
        }
    }

}
